Repository navigation
feat(socrate): ServiceTokenWithScopes, a service token requested with scopes - #125
Merged
Merged
Conversation
…tokens ServiceToken requests no scope, so Socrate issues its default (api) and a service cannot obtain an application-defined scope (Socrate v1.14.0+) that a peer requires with jwtauth.RequireScopes. ServiceTokenWithScopes sends the scopes, with ServiceToken's contract, cached per normalised scope set (at most 16, LRU). Scopes are validated as RFC 6749 scope-tokens before any request; invalid_scope and a response scope lacking a requested scope match the new ErrScopeNotGranted. InvalidateServiceToken also drops scoped tokens. The client_credentials exchange is shared through an unexported helper; ServiceToken's behaviour is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GKRxaeYxyDhmt42cehLsGA
Resolve the CHANGELOG conflict with #124: Added (this change) before Changed (docs), both under Unreleased. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GKRxaeYxyDhmt42cehLsGA
ovander
pushed a commit
that referenced
this pull request
Oct 11, 2026
Moves [Unreleased] under [1.27.0] - 2026-10-11 (#125 ServiceTokenWithScopes, #123 docs), updates the compare links, the README install snippet and the guide's version note. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GKRxaeYxyDhmt42cehLsGA
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
(*socrate.Client).ServiceTokenrequests itsclient_credentialstoken without ascopeparameter, so Socrate issues its defaultapi. Since Socrate v1.14.0, a client can be granted application-defined scopes (<namespace>:<name>, e.g.swingdrift:worker) in itsallowed_scopes, but it has to request them. So a service using backendkit couldn't obtain the scope that a resource server'sjwtauth.RequireScopes("swingdrift:worker")(v1.26.0) requires.New API (additive):
ServiceToken:ClientSecret;("a","b")and("b","a","a")share a token. Each set has its own lock, so different sets don't block each other. At most 16 sets are cached; beyond that the least recently used one is dropped.ServiceTokenfor the default);ClientSecretis missing.invalid_scope(a scope the client doesn't register) matches bothErrScopeNotGrantedand*OAuthError.scopelacks a requested scope isErrScopeNotGranted, naming the missing scopes.scopemeans the request was granted as asked (RFC 6749 §5.1).api. The docs tell callers to listapitoo when they need it.ServiceTokenis unchanged: it has its own cache and still sends noscope. The token exchange moved into a shared unexported helper with identical error texts.InvalidateServiceToken()now also clears the scoped tokens; existing callers have none.docs/CLIENT-INTEGRATION.mdgets the calling side: register the scope in Socrate, then callServiceTokenWithScopes. The README's "app scopes on every grant" is corrected to "when the client requests them".How it was tested
socrate/service_token_scopes_test.go(13 tests, httptest standing in for Socrate's/oauth/token) covers:ServiceTokenis unaffected;-race);invalid_scopeis recognisable;scope, andnullor an absentscopeaccepted;One test added to
service_token_test.gopins down thatServiceTokenaccepts anyscopetype, as before.go mod tidy && git diff --exit-code go.sumleavesgo.sumunchangedgo build ./...passesgo vet ./...passes, also with-tags conformancego test -race -count=1 -timeout=120s ./...passes, also./socrate/...on thego 1.26.0floorgolangci-lint run ./...(v2.14.0) reports no issuegovulncheck ./...: not run locally (vuln.go.devis blocked here); CI runs it. No dependency change.## [Unreleased]inCHANGELOG.md(### Added)Compatibility
(*Client).ServiceTokenWithScopes,ErrScopeNotGranted.InvalidateServiceTokenalso clears scoped tokens, which they don't have. Nothing else.This PR and #124 (the changelog fix) both touch
CHANGELOG.md. I'll mergemaininto whichever merges second.🤖 Generated with Claude Code
https://claude.ai/code/session_01GKRxaeYxyDhmt42cehLsGA
Generated by Claude Code